-
Notifications
You must be signed in to change notification settings - Fork 0
feat:connecting trawl lines between linked buoys #1276
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
src/BuoyTrawlLineLayer/index.js
Outdated
const subjectIsBuoyLineEligible = (subjectFeature = {}, _index, allSubjects = []) => { | ||
const subject = subjectFeature.properties; | ||
|
||
const is_buoy = subject.subject_subtype === 'ropeless_buoy_device'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This string should be a constant. Maybe we won't need it anywhere else so at least putting it at the top of the file like: BUOY_SUBJECT_SUBTYPE
is enough.
Second question: why snake case here (and in all other variables of this method)? It's not our usual approach 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The snake case and non-constantified strings are just me doing this as a quickie/prototype.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed!
src/BuoyTrawlLineLayer/index.js
Outdated
import { useSelector } from 'react-redux'; | ||
|
||
import { getMapSubjectFeatureCollectionWithVirtualPositioning } from '../selectors/subjects'; | ||
import { lineString } from '@turf/turf'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: this import should go in the first block.
src/BuoyTrawlLineLayer/index.js
Outdated
|
||
if (!is_line) return false; | ||
|
||
const line_contains_valid_subjects = devices.every(({ device_id }) => allSubjects.find(({ properties }) => properties.name === device_id)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This variable name sounds odd, it almost sounds like a boolean for a condition: if (lineContainsValidSubjects) ...
but it is not, it's just a list of subjects contained by the line. I guess it needs to be reworded, or maybe just return the one-liner since it's kind of easy to read.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a boolean for a condition -- it's just using Array.prototype.every
to check device presence in the subject list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ohh right, I just understood the every and where this is being used 👍
}; | ||
|
||
const createTrawlLineGeoJSON = (buoySubjectFeatures) => { | ||
return buoySubjectFeatures.reduce((accumulator, { properties }) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Honestly, I've stared at this function for a while haha. I feel like we could make it a bit easier to understand maybe by changing some variable names or not extracting properties from objects like: ({ properties }) => properties.additional...
-> (buoySubjectFeature) => buoySubjectFeature.properties.additional
etc...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Summary version:
We can say that the devices listed for a buoy feature's additional.devices
should be the names of the subjects comprising that trawl.
We can't say that the coordinates included in the additional data devices
array data is up-to-date.
So the eligibility-checker function first ensures a trawl line is completely valid and comprised of available subjects for the user.
Then createTrawlLineGeoJSON
maps those device names back to their subject's last known position and builds out the linestring coordinates from there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense. Maybe a couple tweaks or a brief comment could make that more obvious in the code for future reference.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a descriptive inline comment
src/BuoyTrawlLineLayer/index.js
Outdated
const buoySubjects = mapSubjects.features.filter(subjectIsBuoyLineEligible); | ||
const trawlLineGeoJSON = createTrawlLineGeoJSON(buoySubjects); | ||
|
||
useMapSources([{ id: 'trawl-lines-source', data: trawlLineGeoJSON }]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have constants for sources and layers that we should use to keep our code consistent and the ids accessible. Also, I don't know if you tested the properly addition, update and removal of these sources and layers (seeing Chromes console for warnings and errors), but as I mentioned recently, these hooks don't follow Mapbox sources and layers flows correctly from beginning to end. That's why I think it would be better to stop using them and instead use the map API directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did test absence/presence/filtering etc, and timesliding, and it all works as expected.
I kept the names out of our constants file because I'd like this to be as self-isolated as possible. I will however make the strings constants within this file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh with tested I meant manually. In unit testing we usually use mocks for the map and other methods and the real flow of addition, interaction and removal (or not removal, causing memory leaks) of sources and layers are obscured by all the mocking. Anyway, we agreed this is out of the scope.
About the layers and sources being isolated, why's that 🤔 ? I know this is a feature for the specific scenario of buoy, but I don't get why we don't want to treat it as part of our app if now it is. Just like stationary subjects, or patrols, which are features not everyone use. I feel I'm missing some information or something haha.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh with tested I meant manually.
Me too :-)
"Features not everyone uses" can be considered a spectrum -- with this Buoy work being at one pretty extreme end of the spectrum, "features designed for a specific site and fringe use-cases". It's so specifically for a special sub-project, that I'd rather not pollute the broader app with random BUOY_
variables and references.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The source + layer is very simple and the processing of the source data is clear and well tested 👍
}, { type: 'FeatureCollection', features: [] }); | ||
}; | ||
|
||
const BuoyLineLayer = (_props) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: why the (_props) => {
instead of simply () => {
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just a matter of preference!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean, it's a default linter rule (no-unused-vars
) that we explicitly skip by prefixing the _
. It feels weird to add it intentionally for nothing 🤔
What does this PR do?
How does it look
Relevant link(s)
Where / how to start reviewing (optional)
devices
array in a subject'sadditional
properties, so instead we match thedevice_id
s listed to their subject names and then use the last known position for that subject. @andrejiron21 @doug-nimblegravity should definitely add story work to keep thatdevices
data better refreshed to avoid weird data sync issues in the future.